home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-26 | 9.1 KB | 207 lines | [TEXT/CCL2] |
- ;;; -*- Mode: LISP; Package: (COMPLETION :USE (COMMON-LISP CCL)); Syntax:Common-Lisp; Lowercase: Yes -*-
-
- ;;;; Completion.Lisp
-
- ;;; This file provides a completion facility for fred windows.
- ;;; It is not very sophisticated, but it does useful work!
- ;;; And it´s free.
-
- ;;; Just press c-i for completion of symbols.
-
- ;;; c-i for
- ;;; foo looks in the window package for "FOO"
- ;;; bar:foo looks in the package "BAR" for "FOO" if bar is a known package
- ;;; bar:foo looks in all packages for "FOO" if bar is a unknown package
- ;;; :foo looks in the package "KEYWORD" for "FOO"
-
- ;;; m-i for
- ;;; foo looks in all packages for "FOO"
- ;;; bar:foo looks in all packages for "FOO"
- ;;; :foo looks in all packages for "FOO"
-
- ;;; Written by Rainer Joswig.
- ;;; internet: rainer@ki4.informatik.uni-hamburg.de
-
- ;;; Runs in MCL 2.0b1p3
-
-
- (defpackage "COMPLETION" (:use "CCL" "COMMON-LISP"))
-
- (in-package completion)
-
-
-
- (defun starting-substring-p (substring string length-of-substring)
- "Returns t if substring is a starting substring of string."
- (if (> length-of-substring (length string))
- nil
- (string-equal substring
- string
- :end2 length-of-substring)))
-
-
- (defun find-completing-symbols-in-package (symbol-name-to-complete package)
- "Returns a list of completions for SYMBOL-NAME-TO-COMPLETE in package PACKAGE."
- (declare (type (or string symbol) symbol-name-to-complete))
- (declare (optimize (speed 3) (safety 2)))
- (setf symbol-name-to-complete (string-upcase symbol-name-to-complete))
- (let ((list-of-symbols nil)
- (length-of-symbol-name-to-complete (length symbol-name-to-complete)))
- (do-symbols (symbol package list-of-symbols)
- (when (starting-substring-p symbol-name-to-complete
- (symbol-name symbol)
- length-of-symbol-name-to-complete)
- (push symbol list-of-symbols)))))
-
-
- (defun find-all-completing-symbols (symbol-name-to-complete)
- "Returns a list of all completions for SYMBOL-NAME-TO-COMPLETE."
- (declare (type (or string symbol) symbol-name-to-complete))
- (declare (optimize (speed 3) (safety 2)))
- (setf symbol-name-to-complete (string-upcase symbol-name-to-complete))
- (let ((list-of-symbols nil)
- (length-of-symbol-name-to-complete (length symbol-name-to-complete)))
- (do-all-symbols (symbol list-of-symbols)
- (when (starting-substring-p symbol-name-to-complete
- (symbol-name symbol)
- length-of-symbol-name-to-complete)
- (push symbol list-of-symbols)))))
-
- (defun analyze-string-as-symbol (string default-package)
- "returns symbol and package part of a string analyzed as a symbol"
- (let* ((first-colon-position (position #\: string))
- (second-colon-position (if first-colon-position
- (position #\: string
- :start (1+ first-colon-position))
- nil)))
- (values (if first-colon-position
- (subseq string
- (1+ (or second-colon-position first-colon-position))
- (length string))
- string)
- (if first-colon-position
- (if (zerop first-colon-position)
- (find-package "KEYWORD")
- (find-package (subseq string 0 first-colon-position)))
- default-package))))
-
-
- (defun find-completing-symbols (symbol-name-to-complete
- &key
- (default-package *package*)
- (all-packages nil))
- "Returns a list of completions for SYMBOL-NAME-TO-COMPLETE."
- (declare (type string symbol-name-to-complete))
- (setf symbol-name-to-complete (string-upcase symbol-name-to-complete))
- (multiple-value-bind (symbol package)
- (analyze-string-as-symbol symbol-name-to-complete
- default-package)
- (when symbol
- (if (or all-packages (not package))
- (find-all-completing-symbols symbol)
- (find-completing-symbols-in-package symbol package)))))
-
-
- (defun remove-some-characters-from-string (string)
- "returns: string from-left from-right"
- (let* ((string1 (string-left-trim '(#\# #\') string))
- (deleted-from-left (- (length string) (length string1)))
- (string2 (string-left-trim '(#\|) string1)))
- (incf deleted-from-left (- (length string1) (length string2)))
- (let* ((string3 (string-right-trim '(#\|) string2))
- (deleted-from-right (- (length string2) (length string3))))
- (values string3 deleted-from-left deleted-from-right))))
-
-
- (defun select-one-item-from-list (item-list &rest keys)
- "Like select-item-from-list, but doesn´t ask if there is no or only one item."
- (case (length item-list)
- (0 nil) ; no item
- (1 (first item-list)) ; just one item
- (otherwise ; select one item from many
- (let ((selection (apply #'select-item-from-list
- item-list
- :selection-type :single
- keys)))
- (if (>= (length selection) 1)
- (first selection) ; take the first
- nil))))) ; no selection
-
-
- (defmethod ed-complete-symbol ((window fred-window) &key (all-packages nil))
- "Inserts a completion for the current symbol into the buffer."
- (let ((buffer (fred-buffer window))
- (*package* (or (fred-package window) *package*)))
- (multiple-value-bind (start end)
- (buffer-current-sexp-bounds buffer) ; well, it works
- (if (and start end)
- (when (eq :cancel
- (catch-cancel
- (multiple-value-bind (string-to-be-completed from-start from-end)
- (remove-some-characters-from-string
- (buffer-substring buffer start end))
- (set-mini-buffer window "Completing : ~A" string-to-be-completed)
- (let ((completing-symbol
- (select-one-item-from-list
- (sort (find-completing-symbols
- string-to-be-completed
- :default-package *package*
- :all-packages all-packages)
- #'string<)
- :table-print-function #'prin1
- :window-title "Select a completion.")))
- (if completing-symbol
- (progn
- (collapse-selection window t)
- (buffer-delete buffer (+ start from-start) (- end from-end))
- (buffer-insert buffer
- (string-downcase (prin1-to-string completing-symbol))
- (+ start from-start))
- (set-mini-buffer window "Completion : ~A" completing-symbol))
- (set-mini-buffer window
- "No completion for ~A."
- string-to-be-completed))))))
- (set-mini-buffer window "Completion cancelled."))
- (set-mini-buffer window "Completion : No valid string.")))))
-
-
- (defmethod ed-complete-symbol ((view fred-mixin) &key (all-packages nil))
- "Inserts a completion for the current symbol into the buffer."
- (let ((buffer (fred-buffer view))
- (*package* (or (fred-package view) *package*)))
- (multiple-value-bind (start end)
- (buffer-current-sexp-bounds buffer) ; well, it works
- (when (and start end)
- (catch-cancel
- (multiple-value-bind (string-to-be-completed from-start from-end)
- (remove-some-characters-from-string
- (buffer-substring buffer start end))
- (let ((completing-symbol
- (select-one-item-from-list
- (sort (find-completing-symbols
- string-to-be-completed
- :default-package *package*
- :all-packages all-packages)
- #'string<)
- :table-print-function #'prin1
- :window-title "Select a completion.")))
- (when completing-symbol
- (collapse-selection view t)
- (buffer-delete buffer (+ start from-start) (- end from-end))
- (buffer-insert buffer
- (string-downcase
- (prin1-to-string completing-symbol))
- (+ start from-start))))))))))
-
-
- (defmethod ed-complete-symbol-in-all-packages ((view fred-mixin))
- "Inserts a completion for the current symbol into the buffer."
- (ed-complete-symbol view :all-packages t))
-
-
- (def-fred-command (:control #\i) ed-complete-symbol "c-i")
- (def-fred-command (:meta #\i) ED-COMPLETE-SYMBOL-IN-ALL-PACKAGES "m-i")
-
- (provide 'completion)
-
-